﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Text;
using System.Web;
using System.Web.Services;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Portals;
using DotNetNuke.Framework;
using DotNetNuke.Services.FileSystem;
using DotNetNuke.Entities.Tabs;
using DotNetNuke.Services.Localization;

namespace DotNetNuke.HtmlEditor.TelerikEditorProvider
{
    /// <summary>
    /// Returns a LinkClickUrl if provided a tabid and LinkUrl.
    /// </summary>
    /// <remarks>This uses the new BaseHttpHandler which encapsulates most common scenarios including the retrieval of AJAX request data.
    /// See http://blog.theaccidentalgeek.com/post/2008/10/28/An-Updated-Abstract-Boilerplate-HttpHandler.aspx for more information on 
    /// the BaseHttpHandler.
    /// </remarks>
    public class LinkClickUrlHandler : BaseHttpHandler
    {

        PortalAliasController _portalAliasController = new PortalAliasController();
        UrlController _urlController = new UrlController();

        FileController _fileController = new FileController();
        #region "Private Functions"

        private string GetLinkClickURL(ref DialogParams @params, ref string link)
        {
            link = GetLinkUrl(ref @params, link);
            return "http://" + this.Context.Request.Url.Host + DotNetNuke.Common.Globals.LinkClick(link, @params.TabId, @params.ModuleId, true, false, @params.PortalId, @params.EnableUrlLanguage, @params.PortalGuid);

        }

        private string GetLinkUrl(ref DialogParams @params, string link)
        {
            ArrayList aliasList = _portalAliasController.GetPortalAliasArrayByPortalID(@params.PortalId);

            if (@params.LinkUrl.Contains(@params.HomeDirectory))
            {
                string filePath = @params.LinkUrl.Substring(@params.LinkUrl.IndexOf(@params.HomeDirectory)).Replace(@params.HomeDirectory, "");
                int linkedFileId = _fileController.ConvertFilePathToFileId(filePath, @params.PortalId);
                link = string.Format("fileID={0}", linkedFileId);
            }
            else
            {
                foreach (PortalAliasInfo portalAlias in aliasList)
                {
                    @params.LinkUrl = @params.LinkUrl.Replace(portalAlias.HTTPAlias, "");
                }

                string tabPath = @params.LinkUrl.Replace("http://", "").Replace("/", "//").Replace(".aspx", "");
                string cultureCode = Localization.SystemLocale;

                //Try HumanFriendlyUrl TabPath
                int linkId = TabController.GetTabByTabPath(@params.PortalId, tabPath, cultureCode);

                if (linkId == Null.NullInteger)
                {
                    //Try getting the tabId from the querystring
                    string[] arrParams = @params.LinkUrl.Split('/');
                    for (int i = 0; i <= arrParams.Length - 1; i++)
                    {
                        if (arrParams[i].ToLowerInvariant() == "tabid")
                        {
                            linkId = Convert.ToInt32(arrParams[i + 1]);
                            break;
                        }
                    }
                    if (linkId == Null.NullInteger)
                    {
                        link = @params.LinkUrl;
                    }
                }

            }

            return link;

        }

        private string GetURLType(TabType tabType)
        {
            switch (tabType)
            {
                case Entities.Tabs.TabType.File:
                    return "F";
                case Entities.Tabs.TabType.Member:
                    return "M";
                case Entities.Tabs.TabType.Normal:
                case Entities.Tabs.TabType.Tab:
                    return "T";
                default:
                    return "U";
            }
        }

        private string GetUrlLoggingInfo(ArrayList urlLog)
        {
            StringBuilder fullTableContent = new StringBuilder();
            int maxCount = (urlLog.Count > 100 ? 100 : urlLog.Count);

            fullTableContent.Append("<div class='UrlLoggingInfo' style='width: 100%;'>");

            if ((urlLog.Count > 100))
            {
                fullTableContent.Append("<span>Your search returned <strong>" + urlLog.Count.ToString() + "</strong> results. Showing only the first 100 records ordered by date.</span><br /><br />");
            }

            fullTableContent.Append("<table><tr><th>Date</th><th>User</th></tr>");

            if (maxCount == 0)
            {
                fullTableContent.Append("<tr><td colspan='2'>Your search did not return any results.</td></tr>");
            }
            else
            {
                for (int x = 0; x <= maxCount - 1; x++)
                {
                    UrlLogInfo log = urlLog[x] as UrlLogInfo;
                    fullTableContent.Append("<tr><td>" + log.ClickDate.ToString() + "</td><td>" + log.FullName +
                                            "</td></tr>");
                }
            }

            fullTableContent.Append("</table></div>");

            return fullTableContent.ToString();
        }

        #endregion

        #region "Public Methods"


        public override void HandleRequest()
        {
            string output = null;
            DialogParams @params = Content.FromJson<DialogParams>();
            // This uses the new JSON Extensions in DotNetNuke.Common.Utilities.JsonExtensionsWeb

            string link = @params.LinkUrl;
            @params.LinkClickUrl = link;


            if ((@params != null))
            {
                if ((!(@params.LinkAction == "GetLinkInfo")))
                {
                    if (@params.Track)
                    {
                        string linkUrl = @params.LinkUrl;
                        @params.LinkClickUrl = GetLinkClickURL(ref @params, ref linkUrl);
                        UrlTrackingInfo linkTrackingInfo = _urlController.GetUrlTracking(@params.PortalId, @params.LinkUrl, @params.ModuleId);

                        if (((linkTrackingInfo != null)))
                        {
                            @params.Track = linkTrackingInfo.TrackClicks;
                            @params.TrackUser = linkTrackingInfo.LogActivity;
                            @params.DateCreated = linkTrackingInfo.CreatedDate.ToString();
                            @params.LastClick = linkTrackingInfo.LastClick.ToString();
                            @params.Clicks = linkTrackingInfo.Clicks.ToString();
                        }
                        else
                        {
                            @params.Track = false;
                            @params.TrackUser = false;
                        }
                        @params.LinkUrl = link;

                    }
                }

                switch (@params.LinkAction)
                {
                    case "GetLoggingInfo":
                        //also meant for the tracking tab but this is to retrieve the user information
                        System.DateTime logStartDate = default(System.DateTime);
                        System.DateTime logEndDate = default(System.DateTime);

                        string logText =
                            "<table><tr><th>Date</th><th>User</th></tr><tr><td colspan='2'>The selected date-range did<br /> not return any results.</td></tr>";

                        if (DateTime.TryParse(@params.LogStartDate, out logStartDate))
                        {
                            if (!DateTime.TryParse(@params.LogEndDate, out logEndDate))
                            {
                                logEndDate = logStartDate.AddDays(1);
                            }

                            UrlController _urlController = new UrlController();
                            ArrayList urlLog = _urlController.GetUrlLog(@params.PortalId, GetLinkUrl(ref @params, @params.LinkUrl), @params.ModuleId, logStartDate, logEndDate);

                            if (((urlLog != null)))
                            {
                                logText = GetUrlLoggingInfo(urlLog);
                            }

                        }

                        @params.TrackingLog = logText;
                        break;
                    case "GetLinkInfo":
                        if (@params.Track)
                        {
                            //this section is for when the user clicks ok in the dialog box, we actually create a record for the linkclick urls.
                            if (!@params.LinkUrl.ToLower().Contains("linkclick.aspx"))
                            {
                                @params.LinkClickUrl = GetLinkClickURL(ref @params, ref link);
                            }

                            _urlController.UpdateUrl(@params.PortalId, link, GetURLType(DotNetNuke.Common.Globals.GetURLType(link)), @params.TrackUser, true, @params.ModuleId, false);

                        }
                        else
                        {
                            //this section is meant for retrieving/displaying the original links and determining if the links are being tracked(making sure the track checkbox properly checked)
                            UrlTrackingInfo linkTrackingInfo = default(UrlTrackingInfo);

                            if (@params.LinkUrl.Contains("fileticket"))
                            {
                                var queryString = @params.LinkUrl.Split('=');
                                var encryptedFileId = queryString[1].Split('&')[0];

                                int fileID = Convert.ToInt32(UrlUtils.DecryptParameter(encryptedFileId, @params.PortalGuid));
                                FileInfo savedFile = _fileController.GetFileById(fileID, @params.PortalId);

                                linkTrackingInfo = _urlController.GetUrlTracking(@params.PortalId, string.Format("fileID={0}", fileID), @params.ModuleId);
                                @params.LinkClickUrl = string.Format("{0}{1}{2}{3}/{4}", "http://", this.Context.Request.Url.Host, @params.HomeDirectory, savedFile.Folder, savedFile.FileName).Replace("//", "/");
                            }
                            else
                            {
                                try
                                {
                                    link = @params.LinkUrl.Split('?')[1].Split('&')[0].Split('=')[1];

                                    int tabId = 0;
                                    //if it's a tabid get the tab path
                                    if (int.TryParse(link, out tabId))
                                    {
                                        TabController _tabController = new TabController();
                                        @params.LinkClickUrl = _tabController.GetTab(tabId, @params.PortalId, true).FullUrl;
                                        linkTrackingInfo = _urlController.GetUrlTracking(@params.PortalId, link, @params.ModuleId);
                                    }
                                    else
                                    {
                                        @params.LinkClickUrl = HttpContext.Current.Server.UrlDecode(link);
                                        //get the actual link
                                        linkTrackingInfo = _urlController.GetUrlTracking(@params.PortalId, @params.LinkClickUrl, @params.ModuleId);
                                    }

                                }
                                catch (Exception ex)
                                {
                                    @params.LinkClickUrl = @params.LinkUrl;
                                }
                            }

                            if (linkTrackingInfo == null)
                            {
                                @params.Track = false;
                                @params.TrackUser = false;
                            }
                            else
                            {
                                @params.Track = linkTrackingInfo.TrackClicks;
                                @params.TrackUser = linkTrackingInfo.LogActivity;
                            }

                        }
                        break;
                }
                output = @params.ToJson();
            }
            else
            {
                output = (new DialogParams()).ToJson();
            }

            Response.Write(output);
        }

        public override string ContentMimeType
        {
            //Normally we could use the ContentEncoding property, but because of an IE bug we have to ensure
            //that the UTF-8 is capitalized which requires inclusion in the mimetype property as shown here
            get { return "application/json; charset=UTF-8"; }
        }

        public override bool ValidateParameters()
        {
            //TODO: This should be updated to validate the Content paramater and return false if the content can't be converted to a DialogParams
            return true;
        }

        public override bool HasPermission
        {
            //TODO: This should be updated to ensure the user has appropriate permissions for the passed in TabId.
            get { return Context.User.Identity.IsAuthenticated; }
        }

        #endregion

    }
}
